package net.gazhi.delonix.rbac.web.init;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import net.gazhi.delonix.core.init.AbstractInitService;
import net.gazhi.delonix.core.init.InitService;
import net.gazhi.delonix.core.jpa.Dao;
import net.gazhi.delonix.rbac.entity.Action;
import net.gazhi.delonix.rbac.entity.DX_TABLE;
import net.gazhi.delonix.rbac.entity.MenuItem;
import net.gazhi.delonix.rbac.service.ActionService;

/**
 * 初始化菜单配置
 * 
 * @author Jeffrey Lin
 */
@Service
public class InitMenuService extends AbstractInitService {

	private static final Log logger = LogFactory.getLog(InitMenuService.class);

	@Autowired
	private RequestMappingHandlerMapping mapping;

	@Autowired
	private ActionService actionService;

	@Autowired
	private InitService initApiActionService;

	@Autowired
	private Dao dao;

	@Resource
	private String[] menuItemStrs;

	@Override
	@Transactional
	public boolean checkAndDoInit() throws Exception {
		if (!initApiActionService.isFinished()) {
			return false;
		}
		logger.info("正在初始化 [Menu]...");

		List<MenuItem> items = new ArrayList<MenuItem>(menuItemStrs.length);
		Stack<MenuItem> parents = new Stack<MenuItem>();

		int id = 0;
		for (String itemStr : menuItemStrs) {
			String[] strs = itemStr.split(",");
			String iconStyle = strs[0];
			String name = strs[1];
			String href = strs.length > 2 ? strs[2] : null;
			String target = strs.length > 3 ? strs[3] : null;
			Action action = this.machAction(href);

			// 截取掉 name 左边的 + 号并计算 level(根节点的level为0)
			int level = iconStyle.length();
			iconStyle = StringUtils.trimLeadingCharacter(iconStyle, '+');
			level -= iconStyle.length();

			// 创建对象
			MenuItem item = new MenuItem(++id, iconStyle, name, href, target, action);
			items.add(item);

			// 栈里的级别必须比当前级别高
			while (parents.size() > level) {
				parents.pop();
			}
			if (!parents.isEmpty()) {
				item.setParent(parents.peek());
			}
			// 入栈以备充当后续节点的上级
			parents.push(item);
		}

		dao.createSQLQuery("truncate table " + DX_TABLE.dx_menu_item).executeUpdate();
		dao.saveAll(items);
		dao.flushSession();

		logger.info("初始化 [Menu] 完成。");

		return true;
	}

	private Action machAction(String href) {
		Action action = null;

		if (StringUtils.hasText(href)) {
			HandlerMethod hm = this.machMethod(href);
			if (hm == null) {
				throw new RuntimeException("菜单配置错误：没有加入 MVC 映射 " + href);
			}
			action = actionService.get(Action.generateActionId(hm));
			if (action == null) {
				throw new RuntimeException("菜单配置错误：找不到 Action 记录：" + href);
			}
		}
		return action;
	}

	private HandlerMethod machMethod(String uriPattern) {
		Map<RequestMappingInfo, HandlerMethod> methods = mapping.getHandlerMethods();
		for (RequestMappingInfo info : methods.keySet()) {
			for (String pattern : info.getPatternsCondition().getPatterns()) {
				if (pattern.equals(uriPattern)) {
					HandlerMethod method = methods.get(info);
					return method;
				}
			}
		}
		return null;
	}

}
